﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Newtonsoft.Json;
using System.Diagnostics;

namespace AutoUpdateClient
{
    class Program
    {

        #region 配置
        /// <summary>
        /// 如果服务端版本号高于客户端, 自动更新
        /// </summary>
        public const string version = "/home/version?appName={name}";

        /// <summary>
        /// 根据应用程序名称获取所有状态为 更新,删除,文件列表
        /// </summary>
        public const string getFileList = "/home/getFileList?appName={name}";

        /// <summary>
        /// 根据文件的id, 检查服务器是否存在此文件,返回值大于0, 文件存在,  如果不存在, 更新失败, 服务器文件缺失
        /// </summary>
        public const string fileExist = "/home/fileExist/{id}";

        /// <summary>
        /// 根据文件id开始下载文件
        /// </summary>
        public const string downFile = "/home/downFile/{id}";

        /// <summary>
        /// 读取的配置文件
        /// </summary>
        public static updateConfig config;

        /// <summary>
        /// 从服务器读取的版本号
        /// </summary>
        public static int ver;

        #endregion

        static void Main(string[] args)
        {
            /*
            var config = new updateConfig() { appName = "ScanSystemLog", httpHost = "http://10.8.2.103:23333", version = 0,setupRootPath= AppDomain.CurrentDomain.BaseDirectory, isCallBack=1,callbackExePath="应用程序名称.exe",callBackParams="/autoupload" };
            var str= xmlSerializeUtil.Serializer(config);
            File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "autoUpdate.config", str);
            */

            if (isUpdate())
            {
                Console.WriteLine("update...");
                var list = getUpdateFileList();
                if (list != null && list.Count > 0)
                {
                    // 验证文件是否存在
                    if (checkFileExist(list))
                    {
                        if (string.IsNullOrEmpty(config.setupRootPath))
                        {
                            config.setupRootPath = AppDomain.CurrentDomain.BaseDirectory;
                        }
                        else if (config.setupRootPath[config.setupRootPath.Length - 1] != '/' && config.setupRootPath[config.setupRootPath.Length - 1] != '\\')
                        {
                            config.setupRootPath = (config.setupRootPath + "\\").Replace("/", @"\");
                        }
                        Console.WriteLine("setup ath:" + config.setupRootPath);
                        Console.WriteLine("download file list...");
                        // 开始下载文件列表, 比较文件大小, hashcode, 如果一致则更新成功, 更新配置文件
                        foreach (var item in list)
                        {
                            if (item.fileState.Equals("更新"))
                            {
                                Directory.CreateDirectory(config.setupRootPath + item.fileRealtiveName.Replace(item.fileName, ""));
                                var respon = httpWebResponseUtility.getHttpResponse(config.httpHost + downFile.Replace("{id}", item.id.ToString()));
                                var byts = httpWebResponseUtility.readStream(respon.GetResponseStream());
                                FileStream fs = new FileStream(config.setupRootPath + item.fileRealtiveName, FileMode.Create);
                                fs.Write(byts, 0, byts.Length);
                                fs.Flush();
                                if (item.fileLength != fs.Length)
                                {
                                    fs.Close();
                                    return; // 更新失败, 下载的文件可能不是最新
                                }
                                fs.Close();
                            }
                            else if (item.fileState.Equals("删除"))
                            {
                                FileInfo fi = new FileInfo(config.setupRootPath + item.fileRealtiveName);
                                fi.Delete();
                            }
                        }
                        Console.WriteLine("update success, change update config file...");
                        // 更新配置文件, 升级完成
                        config.version = ver;
                        var str = xmlSerializeUtil.Serializer(config);
                        File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "autoUpdate.config", str);
                    }
                }
            }

            Console.WriteLine("callbackExeName:" + config.callbackExePath == null ? "" : config.callbackExePath);
            Console.WriteLine("callbackParams:" + config.callBackParams == null ? "" : config.callBackParams);
            Console.WriteLine("is callBack:" + (config.isCallBack == 0 ? "no" : "yes"));

            if (config != null && !string.IsNullOrEmpty(config.callbackExePath) && config.isCallBack != 0)
            {
                Console.WriteLine("start callbackExe...");
                // 回调应用程序
                ProcessStartInfo info = new ProcessStartInfo();
                info.FileName = config.callbackExePath;
                info.Arguments = string.IsNullOrEmpty(config.callBackParams) ? "" : config.callBackParams;     // 更新完成立即自动上传, 结束应用程序, 之后才能手动打开
                info.WindowStyle = config.isHidden == 0 ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;
                Process pro = Process.Start(info);
            }
            Console.WriteLine("ok, program exit...");
        }

        #region 网络请求

        /// <summary>
        /// 读取配置文件版本号, 读取服务器版本号, 检查是否需要更新
        /// </summary>
        /// <returns></returns>
        static bool isUpdate()
        {
            if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "autoUpdate.config"))
            {
                var str = File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "autoUpdate.config");
                config = xmlSerializeUtil.Deserialize<updateConfig>(str);
                var respon = httpWebResponseUtility.getHttpResponse(config.httpHost + version.Replace("{name}", config.appName));
                var stream = respon.GetResponseStream();
                // 读取字节流
                var byts = httpWebResponseUtility.readStream(stream);
                ver = Convert.ToInt32(Encoding.UTF8.GetString(byts));
                if (ver > config.version)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 从服务器获取 更新, 删除的文件列表
        /// </summary>
        /// <returns></returns>
        static List<FileNames> getUpdateFileList()
        {
            Console.WriteLine("start get file list...");
            if (config != null)
            {
                var respon = httpWebResponseUtility.getHttpResponse(config.httpHost + getFileList.Replace("{name}", config.appName));
                var byts = httpWebResponseUtility.readStream(respon.GetResponseStream());
                var str = Encoding.UTF8.GetString(byts);
                var list = JsonConvert.DeserializeObject<List<FileNames>>(str);
                return list;
            }
            return new List<FileNames>();
        }

        /// <summary>
        /// 检查文件列表是否存在
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        static bool checkFileExist(List<FileNames> files)
        {
            Console.WriteLine("check server machine exist file list...");
            if (config != null)
            {
                if (files != null && files.Count > 0)
                {
                    foreach (var item in files)
                    {
                        var respon = httpWebResponseUtility.getHttpResponse(config.httpHost + fileExist.Replace("{id}", item.id.ToString()));
                        var str = Encoding.UTF8.GetString(httpWebResponseUtility.readStream(respon.GetResponseStream()));
                        if (str.Equals("0"))
                        {
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        #endregion
    }
}